#pragma once

#include <iostream>
#include <vector>
#include <pthread.h>
#include "Sem.hpp"
using namespace std;

#define MAX_CAP 5
template<class T>
class Circular_queue
{
public:
    Circular_queue()
    :_num(MAX_CAP)
    ,_cir_q(vector<T>(_num))
    ,_cum(Sem_t (0))
    ,_pro(Sem_t (MAX_CAP))
    ,_cur_i(0)
    ,_pro_i(0)
    ,_cum_mtx(pthread_mutex_t())
    ,_pro_mtx(pthread_mutex_t())
    {
        pthread_mutex_init(&_cum_mtx,nullptr);
        pthread_mutex_init(&_pro_mtx,nullptr);
    }

    void push(const T & indata)//生产者进行生产
    {
        _pro.p();//预定空间资源
        pthread_mutex_lock(&_pro_mtx);
        _cir_q[_pro_i++] = indata;
        _pro_i %= MAX_CAP;
        cout<<pthread_self()<<"生产成功 :"<<indata<<endl;
        pthread_mutex_unlock(&_pro_mtx);
        _cum.v();//释放数据资源
        
    }

    void pop(T & outdata)//消费者进行消费
    {
        _cum.p();//预定数据资源
        pthread_mutex_lock(&_cum_mtx);
        outdata = _cir_q[_cur_i++];
        _cur_i %= MAX_CAP;
        cout<<pthread_self()<<"  消费成功 :"<<outdata<<endl;
        pthread_mutex_unlock(&_cum_mtx);
        _pro.v();//释放空间资源
        
        
    }

    ~Circular_queue()
    {
        pthread_mutex_destroy(&_cum_mtx);
        pthread_mutex_destroy(&_pro_mtx);
    }
private:
    //需要有一个队列最大容量的num
    size_t _num;
    //需要有一个队列
    vector<T> _cir_q;

    //需要有两个信号量 分别代表生产者和消费者
    Sem_t _cum;//数据资源
    Sem_t _pro;//空间资源
    //还需要两个下标，分别代表生产者和消费者要生产或消费的数据
    size_t _cur_i;
    size_t _pro_i;

    /*如果是多生产多消费场景，还需要两把锁，一把给生产者-生产者用 一把给消费者-消费者用 因为他们之间是互斥关系*/
    pthread_mutex_t _cum_mtx;
    pthread_mutex_t _pro_mtx;
};